<html>
<head>
    <title>ThreeJs Webgl Performance</title>
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <style>
        body {
            font-family: Monospace;
            background-color: #000;
            color: #fff;
            margin: 0px;
            overflow: hidden;
        }

    </style>
</head>
<body>
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
<!-- <script src="https://threejs.org/examples/js/libs/dat.gui.min.js"></script> -->

<script>

    var camera, scene, renderer, stats, gui;
    var fpsDiv;
    var geometry, mesh;
    var amount = parseInt(window.location.search.substr(1)) || 5;
    var count = Math.pow(amount, 3);
    var group = new THREE.Group();

    let lastTime1 = 0, lastTime2 = 0, lastTime5 = 0; //for every 1s, 2s, 5s
    let lastFrame1 = 0, lastFrame2 = 0, lastFrame5 = 0;
    let fps1 = 0, fps2 = 0, fps5 = 0;
    let frame = 0;
    let triangleCount = 0, vertexCount = 0;

    init();
    animate();

    function init() {
        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.set(0, 0, amount * 2);
        camera.lookAt(0, 0, 0);
        scene = new THREE.Scene();

        const ambientLight = new THREE.AmbientLight(0x101010);
        scene.add(ambientLight);

        const pointLight = new THREE.PointLight(0xffffff, 2, 1000, 1);
        pointLight.position.set(0, 200, 200);
        scene.add(pointLight);

        const spotLight = new THREE.SpotLight(0xffffff, 0.5);
        spotLight.position.set(0, 500, 100);
        spotLight.lookAt(scene.position);
        scene.add(spotLight);

        var segments = 128;
        geometry = new THREE.SphereBufferGeometry(0.4, segments, segments);
        var material = new THREE.MeshPhongMaterial({ color: 0xff0000 });
        if (group) {
          var i = 0;
          var offset = -(amount - 1) / 2;
          for (var x = 0; x < amount; x++) {
            for (var y = 0; y < amount; y++) {
              for (var z = 0; z < amount; z++) {
                var newMesh = new THREE.Mesh(geometry, material);
                newMesh.position.set(offset + x, offset + y, offset + z);
                group.add(newMesh)
              }
            }
          }
        }
        scene.add(group);

        triangleCount = geometry.index.count /3 * count;
        console.log('triangleCount:', triangleCount);
        vertexCount = geometry.attributes.position.count * count;
        console.log('vertexCount:', vertexCount);

        //
        renderer = new THREE.WebGLRenderer({antialias: true});
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);
        const sceneColor = 0x6ad6f0;
        renderer.setClearColor(sceneColor);
        document.body.appendChild(renderer.domElement);
        //
        stats = new Stats();
        document.body.appendChild(stats.dom);

        //add fpsDiv
        fpsDiv = document.createElement("DIV");
        fpsDiv.style.cssText = 'position:fixed;bottom:0;left:10;opacity:0.9;z-index:10000';
        document.body.appendChild(fpsDiv);

        //
        window.addEventListener('resize', onWindowResize, false);
    }

    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    }

    function animate() {
        requestAnimationFrame(animate);
        render();
        stats.update();

    }

    function render() {
        var time = Date.now();
        frame++;

        let deltaFrame, deltaTime;
        if (lastTime1 !== 0) {
            if (time - lastTime1 > 1000) {
                deltaFrame = frame - lastFrame1;
                deltaTime = time - lastTime1;
                fps1 = Math.round(deltaFrame / deltaTime * 1000);
                lastFrame1 = frame;
                lastTime1 = time;
            }
        } else {
            lastTime1 = time;
            lastFrame1 = frame;
        }

        if (lastTime2 !== 0) {
            if (time - lastTime2 > 2000) {
                deltaFrame = frame - lastFrame2;
                deltaTime = time - lastTime2;
                fps2 = Math.round(deltaFrame / deltaTime * 1000);
                lastFrame2 = frame;
                lastTime2 = time;
            }
        } else {
            lastTime2 = time;
            lastFrame2 = frame;
        }

        if (lastTime5 !== 0) {
            if (time - lastTime5 > 5000) {
                deltaFrame = frame - lastFrame5;
                deltaTime = time - lastTime5;
                fps5 = Math.round(deltaFrame / deltaTime * 1000);
                lastFrame5 = frame;
                lastTime5 = time;
            }
        } else {
            lastTime5 = time;
            lastFrame5 = frame;
        }

        //update the fps information
        fpsDiv.innerHTML = `${fps1}(1s) ${fps2}(2s) ${fps5}(5s) T:${triangleCount} V:${vertexCount}`;

        time = time * 0.001;

        group.rotation.x = Math.sin(time / 4);
        group.rotation.y = Math.sin(time / 2);
        renderer.render(scene, camera);
    }
</script>
</body>
</html>
